﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Core
{
    public static partial class status
    {
        public static dynamic getStatus(int rid, string username, bool god)
        {
            var sql = new Sql.SqlDataContext();

            var s = sql.Status.FirstOrDefault(row => row.rid == rid && (god || !row.god));
            if (s == null) return new
            {
                success = false,
                msg = "状态不存在"
            };

            return (from p in sql.Problem
                    from u in sql.User
                    from l in sql.Language
                    where p.pid == s.pid && u.username == s.username && l.code == s.lang
                    let allowCode = s.username == username
                    select new
                    {
                        success = true,
                        s.rid,
                        s.pid,
                        problemTitle = p.title,
                        s.username,
                        u.nickname,
                        submitTime = s.submitTime.toTimeString(),
                        lang = l.title,
                        langCode = s.lang,
                        codeLen = s.code.Length,
                        allowCode,
                        s.exeTime,
                        s.exeMem,
                        status = status2String(s.status),
                        statusCode = s.status,
                        reInfo = allowCode || god ? reCode2String(s.reCode) : null,
                        reCode = allowCode || god ? reCode2Hex(s.reCode) : null,
                        ceInfo = allowCode || god ? s.ceInfo : null
                    }).FirstOrDefault();
        }

        public static string status2String(int status)
        {
            switch (status)
            {
                case 0:
                    return "Waiting";
                case 1:
                    return "Compiling";
                case 2:
                    return "Running";
                case 3:
                    return "Accepted";
                case 4:
                    return "PresentationError";
                case 5:
                    return "TimeLimitExceeded";
                case 6:
                    return "MemoryLimitExceeded";
                case 7:
                    return "OutputLimitExceeded";
                case 8:
                    return "WrongAnswer";
                case 9:
                    return "RuntimeError";
                case 10:
                    return "CompileError";
                default:
                    return "SystemError";
            }
        }

        public static string reCode2String(int? reCode)
        {
            if (!reCode.HasValue) return null;
            switch ((uint)reCode.Value)
            {
                case 0x80000001: return "GuardPageViolation";
                case 0x80000002: return "DataTypeMisalignmen";
                case 0x80000003: return "Breakpoint";
                case 0x80000004: return "SingleStep";
                case 0xC0000005: return "AccessViolation";
                case 0xC000001D: return "IllegalInstruction";
                case 0xC0000025: return "NonContinuableException";
                case 0xC0000026: return "InvaildDisposition";
                case 0xC000008C: return "ArrayBoundsExceeded";
                case 0xC000008D: return "FloatDenormalOperand";
                case 0xC000008E: return "FloatDivideByZero";
                case 0xC000008F: return "FloatInexactResult";
                case 0xC0000090: return "FloatInvalidOperation";
                case 0xC0000091: return "FloatOverflow";
                case 0xC0000092: return "FloatStackCheck";
                case 0xC0000093: return "FloatUnderflow";
                case 0xC0000094: return "IntegerDivideByZero";
                case 0xC0000095: return "IntegerOverflow";
                case 0xC0000096: return "PrivilegedInstruction";
                case 0xC00000FD: return "StackOverflow";
                case 0xC000013A: return "ControlCExit";
                case 0xC00002B4: return "FloatMultipleFaults";
                case 0xC00002B5: return "FloatMultipleTraps";
                case 0xC00002C9: return "RegNatConsumption";
                default: return "Unknow";
            }
        }

        public static string reCode2Hex(int? reCode)
        {
            if (!reCode.HasValue) return null;
            return "0x" + Convert.ToString(reCode.Value, 16).ToUpper();
        }
    }
}
